import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:hong_vpn_new_20240626/hvn_tools/hvn_channel_manager.dart';
import 'package:hong_vpn_new_20240626/ui/location_list/location_list.dart';
import 'package:hong_vpn_new_20240626/utils/Configs/color_config.dart';
import 'package:hong_vpn_new_20240626/utils/api.dart';
import 'package:hong_vpn_new_20240626/utils/models/vpn_list.dart';
import 'package:hong_vpn_new_20240626/utils/zz_navigator.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../utils/global.dart';
import '../utils/utils.dart';

class VpnManager {
  static VpnManager share = VpnManager();

  // VpnListModel? myIp;

  // late List<VpnListModel> vpnList = [];

  VpnListModel? _currVpn;

  /// 当前链接的VPN
  VpnListModel? get currVpn => _currVpn;

  set currVpn(VpnListModel? currVpn) {
    _currVpn = currVpn;
    _cacheCurrVpn();
    eventBus.fire(_currVpn);
  }

  static const String cacheCurrvpnKey = "cache_currvpn_key";

  _cacheCurrVpn() async {
    if (_currVpn != null) {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      // await prefs.setInt(cacheCurrvpnKey, _currVpn!.hotId);
      await prefs.setString(cacheCurrvpnKey, _currVpn!.toJson());
    }
  }

  Future<VpnListModel?> _currCacheVpn() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    var cacheJson = prefs.getString(cacheCurrvpnKey);
    return cacheJson == null ? null : VpnListModel.fromJson(cacheJson);
  }

  init() async {
    // /// 获取当前本地ip信息
    // try {
    //   myIp = await Http.myIp();
    // } catch (e) {
    //   zzLog("myIp Error: $e");
    // }

    // /// 获取VPN列表
    // try {
    //   vpnList = await Http.getVpnList();
    // } catch (e) {
    //   zzLog("vpnList Error: $e");
    // }

    var currVpnId = await _currCacheVpn();

    if (currVpnId != null) {
      currVpn = Global.vpns
              .where((element) => element.hotId == currVpnId.hotId)
              .firstOrNull ??
          currVpnId;
    }
    zzLog("CurrVpn = ${currVpn?.toJson()}");
  }

  connect() async {
    if (currVpn != null) {
      var path = await API.download(currVpn!);
      await HVNChannelManager.share.ovpnConnect(path);
    } else {
      ZZNavigator.push(widget: const LocationListWidget());
    }
  }

  reconnect({bool mustExIp = false}) {
    // if ((Global.firebase.exIp || mustExIp) && currVpn != null) {
    //   var nexIndex = vpnList.indexOf(currVpn!) + 1;
    //   if (nexIndex < vpnList.length) {
    //     currVpn = vpnList[nexIndex];
    //   } else {
    //     currVpn = vpnList.first;
    //   }
    // }
    connect();
  }

  disconnect() async {
    await HVNChannelManager.share.ovpnDisconnect();
  }
}

extension Path on VpnListModel {
  Future<String> get ovpnFilePath async => await _path();

  Future<String> _path() async {
    var directory = await _cacheDirectory();
    String path =
        "${directory.path}/${hotName.replaceAll(RegExp(r' '), '')}_$hotId.ovpn";
    return path;
  }

  static Future<Directory> _cacheDirectory() async {
    Directory directory = await getApplicationDocumentsDirectory();
    String foldPath = "${directory.path}/OvpnFiles";
    Directory foldDirectory = Directory(foldPath);
    if (!foldDirectory.existsSync()) {
      foldDirectory.createSync();
    }
    return foldDirectory;
  }
}

enum OvpnStatus { connected, connecting, disconnected, disconnecting, error }

extension OvpnStatusEx on OvpnStatus {
  static OvpnStatus rawValue(int value) {
    switch (value) {
      case 0:
        return OvpnStatus.connected;
      case 1:
        return OvpnStatus.connecting;
      case 2:
        return OvpnStatus.disconnected;
      case 3:
        return OvpnStatus.disconnecting;
      default:
        return OvpnStatus.error;
    }
  }

  String get title => switch (this) {
        OvpnStatus.connected => "Connected",
        OvpnStatus.connecting => "Connecting",
        OvpnStatus.disconnected => "Disconnected",
        OvpnStatus.disconnecting => "Disconnecting",
        OvpnStatus.error => "Connect Failed",
      };

  String get connectTitle => switch (this) {
        OvpnStatus.connected => "Disconnect",
        OvpnStatus.connecting => "Connecting...",
        OvpnStatus.disconnected => "Connect",
        OvpnStatus.disconnecting => "Disconnecting...",
        OvpnStatus.error => "Connect",
      };

  Color get statusBgColor => switch (this) {
        OvpnStatus.connected => ColorConfig.orange,
        OvpnStatus.connecting => ColorConfig.gray,
        OvpnStatus.disconnected => ColorConfig.gray,
        OvpnStatus.disconnecting => ColorConfig.gray,
        OvpnStatus.error => ColorConfig.gray,
      };
}

class VPNStatus extends ChangeNotifier {
  late OvpnStatus _ovpnStatus = OvpnStatus.disconnected;

  OvpnStatus get status => _ovpnStatus;

  set status(OvpnStatus status) {
    _ovpnStatus = status;
    notifyListeners();
  }

  addListen() {
    HVNChannelManager.toolChannel.setMethodCallHandler((call) async {
      if (call.method == HVNChannelManager.connectVpn) {
        debugPrint("connectVpn ${call.arguments}");
      } else if (call.method == HVNChannelManager.disConnectVpn) {
        debugPrint("disConnectVpn ${call.arguments}");
      } else if (call.method == HVNChannelManager.vpnStatus) {
        debugPrint("vpnStatus ${call.arguments}");
        var status = call.arguments["status"] as int;
        Global.ovpnStatus.status = OvpnStatusEx.rawValue(status);
        eventBus.fire(Global.ovpnStatus);
      }
    });
  }
}
